﻿#include "study10.h"
// C/C++ 标准库学习网站：https://legacy.cplusplus.com
// C/C++ 微软(Visual Studio)中文学习网站：https://learn.microsoft.com/zh-cn/cpp/cpp/?view=msvc-170

using namespace std; // 命名空间声明

size_t num = 0; // 全局变量，用于计数
//#define MAX_SIZE 10 // 最大数据常量
size_t max_size = 10; // 最大数据变量

// 使用异步 future 实现一个简单的生产者消费者模型
static void producer(size_t ms = max_size) {
	//chrono::time_point<chrono::system_clock> start_time; // 时间变量
	while (num < ms) {
		//start_time = chrono::system_clock::now(); // 记录开始时间
		num++;
		cout << "生产者共生产了 " << num << " 个数据" << endl;
		Sleep(500);
	}
}

static void consumer(size_t ms = max_size) {
	size_t count = 0;
	while (count < ms)
	{
		while (num <= count)
		{
			if (num == ms)
				break;
			else {
				Sleep(800);
				continue;
			}
		}
		count++;
		cout << "消费者共消费了 " << count << " 个数据" << endl;
		Sleep(700);
	}
}

void test_async_task() {
	// 异步调用 producer 和 consumer
	future<void> f1 = async(launch::async, producer, max_size); // 异步调用 producer
	future<void> f2 = async(consumer, max_size); // 这里 launch::async 可以省略
	// 当前线程等待异步调用完成
	f1.wait();
	f2.wait();
}

mutex mx; // 定义互斥锁全局变量，用于保护共享资源
static void print_file_content(const string& filename) {
	lock_guard<mutex> lock(mx); // 加锁
	fstream file(filename); // 打开文件
	string lines;
	while (getline(file, lines)) {
		cout << lines << endl; // 打印文件内容
		Sleep(1000); // 休眠一秒
	}
	file.close(); // 关闭文件
	//mx.unlock(); // 解锁
} // lock 退出作用域自动解锁

void test_read_file() {
	//print_file_content("test_file.txt");
	// 异步调用 print_file_content 函数
	future<void> f1 = async(launch::async, print_file_content, "test_file.txt");
	future<void> f2 = async(launch::async, print_file_content, "test_file.txt");
	// 当前线程等待异步调用完成
	f1.wait();
	f2.wait();
	// 可以看到，加锁之后的 print_file_content 函数不在同时输出文件内容

	// 处理返回值
	/*variant<vector<string>, bool> result = f1.get();
	if (holds_alternative<vector<string>>(result)) { // 判断返回值类型
		vector<string> content = get<vector<string>>(result); // 获取返回值
		for (auto& line : content)
			cout << line << endl; // 打印文件内容
	}
	else if (holds_alternative<bool>(result)) { // 判断返回值类型
		bool error = get<bool>(result); // 获取返回值
		if (error)
			cout << "读取文件失败" << endl;
	} */
}

// 字符串优化：使用 std::string_view 代替 std::string
/*static uint32_t s_alloc_count; // 静态变量，记录分配的内存块数量
void* operator new(size_t size) { // new 运算符重载
	if (size == 0)
		return nullptr;
	++s_alloc_count;
	cout << "operator new called, size = " << size << endl;
	return malloc(size); // 调用 malloc() 函数分配内存，重载该操作符是为了查看调试时调用堆栈内存分配的情况
} */
//#define copy_string 1 // 定义宏，用于选择字符串优化方式

#ifdef copy_string
void print_str(const string& str) {
	cout << str << endl; // 打印字符串
}
#else
void print_str(const string_view& str) {
	cout << str << endl; // 打印字符串
}
#endif

void test_string_view() {
	string name_str = "Mr. Smith";
#ifdef copy_string
	// 子字符串提取
	string first_name = name_str.substr(0, 3); // 截取字符串的前 5 个字符，复制
	string last_name = name_str.substr(4, 5); // 通过重载 new 调试可以看到，first_name 和 last_name 都分配了内存
#else
	string_view first_name(name_str.c_str(), 3); // 字符串视图，指向字符串的前 5 个字符
	string_view last_name = string_view(name_str.c_str() + 4, 5); // 字符串视图，指向字符串的第 5-10 个字符
	// 字符串视图可以避免拷贝字符串，节省内存和时间开销
#endif
	// 字符串视图可以作为函数参数传递，避免拷贝字符串，节省内存和时间开销
	print_str(first_name); // 打印字符串
	print_str(last_name); // 打印字符串
}
